<?php

/*
  Created on : 2016-3-20, 15:33:03
  Author     : dongtao <dongtao@xiaomi.com>
 */

class PDOMysql {
    /*
     * 数据库配置
     */
    private $_db_config = null;

    /*
     * 数据库连接
     */
    private $_db = '';
    
    /*
     * 实例
     */
    static $_instance = array();
    
    /*
     * 操作结果
     */
    private $_result = '';

    /*
     * 当前数据库连接
     */
    private $_link = '';

    /*
     * 默认字符集
     */
    private $_charset = 'utf8';

    /*
     * 构造函数
     */
    function __construct($db_config) {
        $this->_db_config = $db_config;
    }
    
    /*
     * 获取实例
     */
    public static function getInstance($id){
        if(!isset(self::$_instance[$id])){
            $config = Loader::loadCfg('db');
            $db_config = $config[$id];
            self::$_instance[$id] = new static($db_config); 
        }
        return self::$_instance[$id];
    }

    /*
     * 连接数据库
     */
    function connect() {
        $db_config = $this->_db_config;
        $db_key = genObjectId($db_config);
        if (!isset($this->_db[$db_key])) {
            $dsn = "mysql:host={$db_config['host']};port={$db_config['port']};dbname={$db_config['dbname']}";
            try {
                if (empty($db_config['charset'])) {
                    $db_config['charset'] = $this->_charset;
                }
                $driver_options = array(
                    PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES {$db_config['charset']}",
                    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
                );
                $this->_db[$db_key] = new PDO($dsn, $db_config['usr'], $db_config['pwd'], $driver_options);
            } catch (PDOException $exc) {
                throw new Exception($exc->getMessage(), $exc->getCode());
            }
        }
        $this->_link = $this->_db[$db_key];
        return $this->_link;
    }
    
    /*
     * 返回上一个更新id
     */
    public function lastInsertId(){
        return $this->_link->lastInsertId();
    }

    /*
     * 执行语句
     */
    public function excute($sql,$sqldata){
        $this->connect();
        $this->_result =  $this->_link->prepare($sql);
        $result = $this->_result->execute($sqldata);
        return $result;
    }
    
     /*
     * 执行语句
     */
    public function exec($sql){
        $this->connect();
        $result =  $this->_link->exec($sql) or die(print_r($this->_link->errorInfo(), true));
        return $result;
    }
    
    
    /*
     * 返回指定sql结果中的第一行
     */
    public function fetchRow($sql,$sqldata,$mode = PDO::FETCH_ASSOC){
        $result = $this->excute($sql, $sqldata);
        $this->_result->setFetchMode($mode);
        return $this->_result->fetch();    
    }
    
    /*
     * 返回指定sql结果
     */
    public function fetchAll($sql,$sqldata,$mode = PDO::FETCH_ASSOC){
        $result = $this->excute($sql, $sqldata);
        $this->_result->setFetchMode($mode);
        return $this->_result->fetchAll();    
    }
    
    /**
     * 批量插入
     * @param table $table
     * @param array $data   二维数组
     * @param array $fields 指定需要插入的值, 为空则使用$data中所有key
     * @param string $type insert|ignore|replace
     * @return int
     */
    public function insertMulti($table, array $data, array $fields = array(), $type = 'insert')
    {
        $fields  = $fields ? : array_keys(current($data));
        $values  = '';
        $sqldata = array();
        $i       = 0;
        foreach ($data as $row)
        {
            $i++;
            $value = null;
            foreach ($fields as $key)
            {
                $bind_key           = ":__{$key}_{$i}__";
                $val                = isset($row[$key]) ? $row[$key] : null;
                $sqldata[$bind_key] = $val;
                $value .= "{$bind_key},";
            }
            $values .= '(' . trim($value, ',') . '),';
        }
        $fields = '`' . implode('`,`', $fields) . '`';
        $values = trim($values, ',');

        $sql_before = null;
        switch ($type)
        {
            case 'replace':
                $sql_before = 'REPLACE';
                break;

            case 'ignore':
                $sql_before = 'INSERT IGNORE';
                break;

            case 'insert':
            default:
                $sql_before = 'INSERT';
                break;
        }

        $sql = "{$sql_before} INTO `{$table}` ({$fields}) VALUES {$values}";
        return $this->excute($sql, $sqldata);
    }
    
    /**
     * 更新多行记录，
     * @param string $table
     * @param array  $data        待更新的二维数组
     * @param string $index_field 用于判断的字段名，本字段需要在$data第二维中存在
     * @param string $condition
     * @param array  $condata
     * @return boolean
     */
    public function updateMulti($table, array $data, $index_field, $condition, array $condata = array())
    {
        $slist      = array();
        $sqldata    = array();
        $field_case = array();
        $i          = 0;
        foreach ($data as $row)
        {
            $i++;
            $row_keys = array_keys($row);
            if (!isset($row[$index_field]))
            {
                return false;
            }

            foreach ($row_keys as $key)
            {
                if ($key === $index_field)
                {
                    continue;
                }

                $bind_index_key           = ":_index_field_{$i}";
                $bind_value_key           = ":_{$key}_{$i}";
                $sqldata[$bind_index_key] = $row[$index_field];
                $sqldata[$bind_value_key] = $row[$key];

                $field_case[$key][] = " WHEN `{$index_field}` = {$bind_index_key} THEN {$bind_value_key} ";
            }
        }

        foreach ($field_case as $field => $v)
        {
            $case    = "`$field`=CASE " . implode($v, ' ') . " END";
            $slist[] = $case;
        }

        // 如果指定了条件，则跟上条件串
        if (!empty($condition))
        {
            $condition = " WHERE " . $condition;
        }

        $sql = "UPDATE `{$table}` SET " . implode(',', $slist) . $condition;
        return $this->excute($sql, array_merge($sqldata, $condata));
    }
    

}
